package app.controllers;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.util.DateParseException;

import app.models.Consulta;
import app.models.Convenio;
import app.models.Especialidade;
import app.models.Funcionario;
import app.models.SubEspecialidade;
import app.models.enums.TipoConsulta;
import app.models.enums.TipoFluxoCaixa;
import app.models.to.RelatorioConsulta;
import app.models.to.RelatorioFaturamento;
import app.models.to.RelatorioLog;
import app.services.ConsultaService;
import app.services.ConvenioService;
import app.services.EspecialidadeService;
import app.services.FuncionarioService;
import app.services.RelatorioService;
import app.services.SubEspecialidadeService;
import app.util.Constants;
import app.util.DateUtils;
import app.util.PlanningReport;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.interceptor.download.Download;
import br.com.caelum.vraptor.jasperreports.Report;
import br.com.caelum.vraptor.jasperreports.download.ReportDownload;
import br.com.caelum.vraptor.jasperreports.formats.ExportFormats;
import br.com.caelum.vraptor.validator.ValidationMessage;

@Resource
public class RelatorioController extends Controller {

	private final Result result;
	private final RelatorioService service;
	private final ConsultaService consultaService;
	private final ConvenioService convenioService;
	private final EspecialidadeService especialidadeService;
	private final SubEspecialidadeService subEspecialidadeService;
	private final FuncionarioService funcionarioService;
	private final Validator validator;
	private final HttpServletResponse response;
	private final HttpServletRequest request;
	
	public RelatorioController(Result result, RelatorioService service, ConsultaService consultaService,
			EspecialidadeService especialidadeService, SubEspecialidadeService subEspecialidadeService,
			FuncionarioService funcionarioService, ConvenioService convenioService,
			Validator validator, HttpServletResponse response, HttpServletRequest request) {

		this.result = result;
		this.service = service;
		this.consultaService = consultaService;
		this.especialidadeService = especialidadeService;
		this.subEspecialidadeService = subEspecialidadeService;
		this.funcionarioService = funcionarioService;
		this.validator = validator;
		this.response = response;
		this.request = request;
		this.convenioService = convenioService;
	}
	
	@Get("/relatorios/faturamento")
	public Download faturamento(RelatorioFaturamento relatorioFaturamento) throws ParseException, DateParseException {
		
		result.include("tipos", TipoFluxoCaixa.values());
		
		validateFilter(relatorioFaturamento.getDataInicial(), relatorioFaturamento.getDataFinal());

		List<RelatorioFaturamento> faturamentos = new ArrayList<RelatorioFaturamento>();
		
		if (null != relatorioFaturamento) {
			if((relatorioFaturamento.getDataInicial() != null && !relatorioFaturamento.getDataInicial().isEmpty()) || (relatorioFaturamento.getDataFinal() != null && !relatorioFaturamento.getDataFinal().isEmpty())){
				faturamentos = service.findRelatorioFaturamentosByFilters(relatorioFaturamento);
			}
		}
		
		// Ação de acordo com "submit" acionado
		if (null != request.getParameter("submit")) {
			if (request.getParameter("submit").equals("Limpar")) {
				relatorioFaturamento = new RelatorioFaturamento();
			}
			
			if (request.getParameter("submit").equals("Exportar PDF")) {
				return pdfPlanningReport(faturamentos, "relatorio_faturamentos.jasper");
			}
			
			if (request.getParameter("submit").equals("Exportar Excel")) {
				return xlsPlanningReport(faturamentos, "relatorio_faturamentos.jasper");
			}
		}
		
		if((relatorioFaturamento.getDataInicial() != null && !relatorioFaturamento.getDataInicial().isEmpty()) || (relatorioFaturamento.getDataFinal() != null && !relatorioFaturamento.getDataFinal().isEmpty())){
			result.include("faturamentos", faturamentos);
		} else {
			validator.add(new ValidationMessage(bundle.getString("period.empty"), Constants.ERROR));
		}
		
		result.include("relatorioFaturamento", relatorioFaturamento);
		
		validator.onErrorForwardTo(this).faturamento();
		
		result.forwardTo(this).faturamento();
		
		return null;
	}
	
	@Get("/relatorios/consulta")
	public Download consulta(Consulta consulta) throws ParseException, DateParseException {

		result.include("tipos", TipoConsulta.values());
		
		validateFilter(consulta.getDataInicial(), consulta.getDataFinal());
		
		List<RelatorioConsulta> relatorioConsultas = new ArrayList<RelatorioConsulta>();
		
		if (null != consulta) {
			if((consulta.getDataInicial() != null && !consulta.getDataInicial().isEmpty()) || (consulta.getDataFinal() != null && !consulta.getDataFinal().isEmpty())){
				relatorioConsultas = service.findRelatorioConsultasByFilters(consulta);
			}
		}
		
		// Ação de acordo com "submit" acionado
		if (null != request.getParameter("submit")) {
			
			if (request.getParameter("submit").equals("Limpar")) {
				consulta = new Consulta();
			}
			
			if (request.getParameter("submit").equals("Exportar PDF")) {
				return pdfPlanningReport(relatorioConsultas, "relatorio_consultas.jasper");
			}
			
			if (request.getParameter("submit").equals("Exportar Excel")) {
				return xlsPlanningReport(relatorioConsultas, "relatorio_consultas.jasper");
			}
		}
		
		if (consulta.getTipo() == TipoConsulta.PARTICULAR) {
			List<Especialidade> especialidades = especialidadeService.findAllOrdered();
			
			result.include("especialidades", especialidades);
		} else if (consulta.getTipo() == TipoConsulta.CONVENIO) {
			List<SubEspecialidade> subEspecialidades = subEspecialidadeService.findAllOrdered();
			
			result.include("subEspecialidades", subEspecialidades);
		}
		
		List<Convenio> convenios = convenioService.findAll();
		result.include("convenios", convenios);
		
		List<Funcionario> especialistas = funcionarioService.findAllOrdered();
		
		if (null != consulta.getIdEspecialidade()) {
			Especialidade especialidade = especialidadeService.find(consulta.getIdEspecialidade().longValue());
				
			result.include("especialistas", funcionarioService.findEspecialistasByEspecialidade(especialidade.getId()));
		} else if (null != consulta.getIdSubEspecialidade()) {
			SubEspecialidade subEspecialidade = subEspecialidadeService.find(consulta.getIdSubEspecialidade().longValue());
				
			result.include("especialistas", funcionarioService.findEspecialistasByEspecialidade(Long.valueOf(subEspecialidade.getEspecialidade().getId())));
		} else {
			result.include("especialistas", especialistas);
		}
		
		if((consulta.getDataInicial() != null && !consulta.getDataInicial().isEmpty()) || (consulta.getDataFinal() != null && !consulta.getDataFinal().isEmpty())){
			result.include("consultas", consultaService.findConsultasByFilters(consulta, null, null, null));
		} else {
			validator.add(new ValidationMessage(bundle.getString("period.empty"), Constants.ERROR));
		}
		
		result.include("consulta", consulta);
		
		validator.onErrorForwardTo(this).consulta();
		
		result.forwardTo(this).consulta();
		
		return null;
	}
	
	@Get("/relatorios/log")
	public Download log(RelatorioLog relatorioLog) throws ParseException, DateParseException {
		
		validateFilter(relatorioLog.getDataInicial(), relatorioLog.getDataFinal());

		List<RelatorioLog> logs = new ArrayList<RelatorioLog>();
		
		if (null != relatorioLog) {
			if((relatorioLog.getDataInicial() != null && !relatorioLog.getDataInicial().isEmpty()) || (relatorioLog.getDataFinal() != null && !relatorioLog.getDataFinal().isEmpty())){
				logs = service.findRelatorioLogsByFilters(relatorioLog);
			}
		}
		
		// Ação de acordo com "submit" acionado
		if (null != request.getParameter("submit")) {
			if (request.getParameter("submit").equals("Limpar")) {
				relatorioLog = new RelatorioLog();
			}
			
			if (request.getParameter("submit").equals("Exportar PDF")) {
				return pdfPlanningReport(logs, "relatorio_log.jasper");
			}
			
			if (request.getParameter("submit").equals("Exportar Excel")) {
				return xlsPlanningReport(logs, "relatorio_log.jasper");
			}
		}
		
		result.include("relatorioLog", relatorioLog);
		
		if((relatorioLog.getDataInicial() != null && !relatorioLog.getDataInicial().isEmpty()) || (relatorioLog.getDataFinal() != null && !relatorioLog.getDataFinal().isEmpty())){
			result.include("logs", logs);
		} else {
			validator.add(new ValidationMessage(bundle.getString("period.empty"), Constants.ERROR));
		}
		
		validator.onErrorForwardTo(this).log();
		
		result.forwardTo(this).log();
		
		return null;
	}
	
	public Download pdfPlanningReport(List paramList, String template) {
        Report report = new PlanningReport(paramList, template);
        
        ReportDownload download = new ReportDownload(report, ExportFormats.pdf(), false);
        
        response.setHeader("Content-disposition", "inline; filename=" + download.getFileName() + ";");
        
        return download;
    }
	
    public Download xlsPlanningReport(List paramList, String template) {
        Report report = new PlanningReport(paramList, template);
        
        ReportDownload download = new ReportDownload(report, ExportFormats.xlsx(), true);
        
        return download;
    }
    
	public void validateFilter(String dataInicial, String dataFinal) throws ParseException {
		if (null != dataInicial && null != dataFinal && "" != dataInicial && "" != dataFinal) {
			if (DateUtils.validatePeriodIncompatible(dataInicial, dataFinal)) {
				validator.add(new ValidationMessage("A Data inicial não pode ser maior que a Data final.", "error"));
			} else {
				if (DateUtils.validatePeriodMoreThan(dataInicial, dataFinal, 90)) {
					validator.add(new ValidationMessage("O período não pode ser maior que 3 meses.", "error"));
				}
			}
		} else {
			validator.add(new ValidationMessage("Defina um período de no maximo 90 dias para o relatório.", "info"));
		}
	}
	
    // Metódos criados apenas para redirecionamentos de páginas.
	public void consulta() { }
	public void faturamento() { }
	public void log() { }
	
}
